package cn.hallele.leinsteining.ms.support.starter.context.impl;

import cn.hallele.leinsteining.mc.infrastructure.flow.context.BaseContext;
import cn.hallele.leinsteining.mc.infrastructure.metadata.constants.MsgCodeConst;
import cn.hallele.leinsteining.mc.infrastructure.metadata.exceptions.children.ParamException;
import cn.hallele.leinsteining.mc.infrastructure.util.bean.CastUtil;
import cn.hallele.leinsteining.ms.support.starter.context.Context;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * 基础上下文
 *
 * @author anle5
 * @since 2024/7/26 21:22
 */
@Slf4j
public class LeInSteiningContext extends BaseContext implements Context {
    /**
     * 上下文获取内容，注意，只适合上下文没有相同类型字段得到情况
     *
     * @param tClass tClass
     * @return 获取目标
     */
    @Override
    public <T> T getField(Class<T> tClass) {
        Class<? extends LeInSteiningContext> aClass = this.getClass();

        Stream<Field> fieldStream = Arrays.stream(aClass.getDeclaredFields()).filter(f -> f.getType() == tClass);
        List<Field> result = fieldStream.toList();
        if (result.size() != 1) {
            log.error("Can't find the field of type [{}].Too many or none,matched fields count: {}, list: {}",
                    tClass.getName(), result.size(), result.stream().map(Field::getName).toList());
            throw new ParamException(MsgCodeConst.PARAMETER_ERROR, tClass.getName());
        }

        return CastUtil.cast(getFieldValue(result.get(0)));
    }

    /**
     * 获取field字段值
     *
     * @param field field
     * @return Object
     */
    protected Object getFieldValue(Field field) {
        try {
            field.setAccessible(true);
            return field.get(this);
        } catch (IllegalAccessException e) {
            log.error(e.getMessage(), e);
            throw new ParamException(MsgCodeConst.PARAMETER_ERROR, field.getName());
        }
    }
}
